Java JavaScript Python C# C C++ Go Kotlin PHP Swift R Ruby TypeScript Scala SQL Perl rust VisualBasic Matlab Julia

Generics → Unbounded Wildcards

Generics

Unbounded Wildcards

Unbounded wildcards in Java, represented by `?`, are used when you want to work with a collection (like a `List`, `Set`, or `Map`) without specifying the exact type of objects it contains. This is useful when you only need to perform operations that are common to *all* types of objects. It's a way to achieve greater flexibility and code reusability compared to using a specific type parameter.

Without Unbounded Wildcards (Incorrect Approach)

Without Unbounded Wildcards import java.util.List; public class Main { public void printCollectionSize(List<String> list) { System.out.println("Size: " + list.size()); } public static void main(String[] args) { List<String> stringList = List.of("apple", "banana"); //List<Integer> intList = List.of(1, 2, 3); //List<Double> doubleList = List.of(1.1, 2.2, 3.3); Main printer = new Main(); printer.printCollectionSize(stringList); } }

Output

Size: 2
This method only works with `List<String>`. If you try to pass a `List<Integer>` or `List<Double>`, you'll get a compilation error.

With Unbounded Wildcards (Correct Approach)

generic With Unbounded Wildcards import java.util.List; public class Main { public void printCollectionSize(List<?> list) { System.out.println("Size: " + list.size()); } public static void main(String[] args) { List<String> stringList = List.of("apple", "banana"); List<Integer> intList = List.of(1, 2, 3); List<Double> doubleList = List.of(1.1, 2.2, 3.3); Main printer = new Main(); printer.printCollectionSize(stringList); printer.printCollectionSize(intList); printer.printCollectionSize(doubleList); } }

Output

Size: 2 Size: 3 Size: 3
The `?` wildcard means "any type". The `size()` method is available for any `List`, regardless of the type parameter, so this method compiles and works correctly with any type of list.

Limitations of Unbounded Wildcards

The crucial limitation is that you cannot add elements to a collection with an unbounded wildcard. You can only read elements.
limitations public void addToCollection(List<?> list) { // list.add("hello"); // This will result in a compile-time error! }
The compiler doesn't know what type of elements the list can hold, so it prevents you from adding anything to prevent runtime type errors.

Example illustrating getting elements

You can read elements, but you have to treat them as `Object`:
unbounded wildcard public void printCollectionElements(List<?> list) { for (Object element : list) { System.out.println(element); } }
This works because all types in Java ultimately extend `Object`. However, you would need to cast each element to its specific type if you want to use type-specific methods.

Unbounded Wildcards with other Collection types

The same principle applies to other collection types like `Set` and `Map`.
Unbounded Wildcards with other Collection types import java.util.List; import java.util.Set; import java.util.HashSet; import java.util.Map; import java.util.HashMap; public class Main { public void printCollectionSize(List<?> list) { System.out.println("List Size: " + list.size()); } public void printSetSize(Set<?> set) { System.out.println("Set Size: " + set.size()); } public void printMapSize(Map<?, ?> map) { // Note: two wildcards for key and value System.out.println("Map Size: " + map.size()); } public static void main(String[] args) { List<String> stringList = List.of("apple", "banana"); List<Integer> intList = List.of(1, 2, 3); List<Double> doubleList = List.of(1.1, 2.2, 3.3); Map<String, Integer> map1 = new HashMap<>(); map1.put("one", 1); Set<Integer> set1 = new HashSet<>(); set1.add(2); Main printer = new Main(); printer.printCollectionSize(stringList); printer.printCollectionSize(intList); printer.printCollectionSize(doubleList); printer.printSetSize(set1); printer.printMapSize(map1); } }

Output

List Size: 2 List Size: 3 List Size: 3 Set Size: 1 Map Size: 1
In summary: Unbounded wildcards (`?`) provide flexibility by allowing methods to operate on collections of any type, but this comes with the restriction that you can only read elements (treating them as `Object`), and not add elements to the collection. They're a powerful tool for creating generic methods that work across a wide range of collection types when you only need to perform read-only operations. When you need to add or modify elements, you'll need to use bounded wildcards (covered in other explanations).

Tutorials